package com.modular.redis;

import cn.hutool.core.thread.lock.LockUtil;
import cn.hutool.core.util.StrUtil;
import com.modular.exception.ModularException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

@Component
public class LockUtils {
    private static Logger logger = LoggerFactory.getLogger(LockUtil.class);

    @Resource
    private RedisLockRegistry redisLockRegistry;

    private final Integer THREE = 3;
    /**
     * 默认锁定3秒
     * @param lockKey
     * @param lockCallBack
     */
    public void lockThreeSeconds(String lockKey, ILockCallBack lockCallBack){
        lock(lockKey,null, THREE,lockCallBack);
    }

    /**
     * 默认锁定3秒
     * @param lockKey
     * @param lockCallBack
     */
    public void lock(String lockKey, Integer expireSeconds, ILockCallBack lockCallBack){
        lock(lockKey,null, expireSeconds,lockCallBack);
    }

    public void lock(String lockKey, String errorMsg, Integer expireSeconds, ILockCallBack lockCallBack) {
        Lock lock = redisLockRegistry.obtain(lockKey);
        try {
            if (expireSeconds != null) {
                if (!lock.tryLock(expireSeconds, TimeUnit.SECONDS)) {
                    logger.error(lockKey + " 锁获取失败");
                    throw new ModularException(StrUtil.isNotBlank(errorMsg) ? errorMsg : "请求频繁，请稍后再操作");
                }
            } else {
                if (!lock.tryLock()) {
                    logger.error(lockKey + " 锁获取失败");
                    throw new ModularException(StrUtil.isNotBlank(errorMsg) ? errorMsg : "请求频繁，请稍后再操作");
                }
            }
        }catch(ModularException e){
            throw e;
        }catch(Exception e){
            throw new ModularException(StrUtil.isNotBlank(errorMsg) ? errorMsg : "请求频繁，请稍后再操作");
        }

        try {
            lockCallBack.excuteLockService();
        } finally {
            if (lock != null) {
                try {
                    lock.unlock();
                } catch (Exception e) {
                    logger.error(lockKey + " 锁释放异常", e);
                }
            }
        }
    }

    public  interface ILockCallBack{
        void excuteLockService();
    }
}
